import sys
import cPickle
import os
import time
import fcntl
import string
import random
import types
import socket
import hashlib
import threading
import traceback

from bsddb3 import db

#import simplejson as json

from client import DbmAuthException
from client import DbmException

"""
    Copyright (C) 2009, 2010  Jorge Alegre Vilches

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
"""


class Locking:
	PathDict = {}
	__sPathHomeEnv = ''
	__sEnvName= ''
	def __init__(self, sPathHomeEnv, sEnvName):
		self.PathDict = {}
		self.__sPathHomeEnv = sPathHomeEnv
		self.__sEnvName = sEnvName
	def acquire(self, path):
		if path[0] != '/':
			path = self.__sPathHomeEnv + '/' + self.__sEnvName + '/data/' + path
		PathFields = string.split(path, self.__sPathHomeEnv + '/')
		if len(PathFields) >= 2:
			pathLock = self.__sPathHomeEnv + '/locks/' + string.replace(PathFields[1], '/','.') + '.lock'
		else:
			path = string.replace(path[1:], '/', '.')
			pathLock = self.__sPathHomeEnv + '/locks/' + path + '.lock'
		#print 'pathLock=>', pathLock
		fLock = open(pathLock,'w')
		fcntl.lockf(fLock.fileno(), fcntl.LOCK_EX)
		self.PathDict[path] = (fLock, pathLock)
	def release(self, path):
		if path[0] != '/':
			path = self.__sPathHomeEnv + '/' + self.__sEnvName + '/data/' + path
		PathFields = string.split(path, self.__sPathHomeEnv + '/')
		if len(PathFields) == 1:
			path = string.replace(path[1:], '/', '.')
		#print 'Unlock=>', path
		if self.PathDict.has_key(path):
			Tuple = self.PathDict[path]
			fLock = Tuple[0]
			pathLock = Tuple[1]
			try:
				fcntl.lockf(fLock.fileno(), fcntl.LOCK_UN)
				fLock.close()
				if os.path.isfile(pathLock):
					os.remove(pathLock)
			except:
				if os.path.isfile(pathLock):
					os.remove(pathLock)
				raise
			del self.PathDict[path]

class Date:

	def __init__(self):
		self._time = time.time()

	def log_format(self):
		time_tuple = time.localtime(self._time)
		time_str = time.strftime('[%d/%b/%Y %H:%M:%S]', time_tuple)
		return time_str		

class Log:

	WRITE_DATE = 1
	file = None

	def __init__(self):
		pass

	def disableDate(self):
		self.WRITE_DATE = 0

	def enableDate(self):
		self.WRITE_DATE = 1

	def open(self, path):
		"""Open a file."""
		self.file = open(path, 'a')

	def write(self, text):
		"""Writes logging data, keeping correct syntax."""
		if self.WRITE_DATE:
			oDate = Date()
			dateStr = oDate.log_format()
			text = dateStr + ' ' + text + '\015\012'
		self.file.write(text)

	def close(self):
		"""Closes a logging file."""
		self.file.close()

class ErrorLog(Log):

	def __init__(self):
		self.disableDate()

class DbServerHandler:
	_oLocking = None
	_PathLockWrite = ''
	__SYS_ACCOUNT = ''
	__PATH_ERROR = ''
	__PATH_HOME_ENV = ''
	__ENCODING = 'utf-8'
	def __init__(self, request, client_address, server):
		self.request = request
		self.client_address = client_address
		self.server = server
		self.allow_reuse_address = 1
		self.__SYS_ACCOUNT = self.server.DataDict['SYS_ACCOUNT']
		self.__PATH_ERROR = self.server.DataDict['PATH_ERROR']
		self.__PATH_ERROR_DETAIL = self.server.DataDict['PATH_ERROR_DETAIL']
		self.__PATH_HOME_ENV = self.server.DataDict['PATH_HOME_ENV']
		self.ThreadLock = self.server.ThreadLock
		try:
			self.setup()
			self.handle()
			self.finish()
		finally:
			sys.exc_traceback = None    # Help garbage collection
	def setup(self):
		pass
	def _log(self):
		pass
	def _waitForUnlock(self):
		check = self.server.DataDict['lock']
		while check:
			time.sleep(10)
			check = self.server.DataDict['lock']
	def _raiseTableException(self, sOp, sContainer):
		raise DbmException(sOp, sContainer)
	def _lockDb(self, sPathLock, sEnvName, bSys=True):
		if bSys:
			self._oLocking = Locking(self.__PATH_HOME_ENV, sEnvName)
			self._oLocking.acquire(sPathLock)
		else:
			self._oLocking = Locking(sPathLock, sEnvName)
			self._oLocking.acquire(sPathLock)
	def _unlockDb(self, sPathLock):
		self._oLocking.release(sPathLock)
	def __toStringDict(self, Dict):
		"""
		@param Dict: Dictionary with unicode keys
		@return: Dict: Dictionary with string keys
		"""
		List = Dict.keys()
		NewDict = {}
		for sKey in List:
			sValue = Dict[sKey]
			if type(sValue) == types.StringType or type(sValue) == types.UnicodeType:
				try:
					sValue = str(sValue)
				except UnicodeEncodeError:
					# Should check encoding from data, then apply encoding
					sValue = sValue.encode('utf-8')
			NewDict[str(sKey)] = sValue
		return NewDict
	def _open(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'open'
			bLock = self.ThreadLock.acquire()
			try:
				#print 'RequestDict: ', RequestDict
				if RequestDict.has_key('sPath'):
					sPath = RequestDict['sPath']
				if RequestDict.has_key('iDbType'):
					iDbType = RequestDict['iDbType']
				if RequestDict.has_key('sDbName'):
					sDbName = RequestDict['sDbName']
				if RequestDict.has_key('iFlagsOpen'):
					iFlagsOpen = db.DB_THREAD | RequestDict['iFlagsOpen']
				else:
					iFlagsOpen = db.DB_THREAD
				if RequestDict.has_key('iFlagsAdd'):
					iFlagsAdd = RequestDict['iFlagsAdd']
				if RequestDict.has_key('iFileMode'):
					iFileMode = RequestDict['iFileMode']
				if RequestDict.has_key('sEnvName'):
					sEnvName = RequestDict['sEnvName']
				if RequestDict.has_key('iTxn'):
					iTxn = RequestDict['iTxn']
				if RequestDict.has_key('sMode'):
					sMode = RequestDict['sMode']
				if RequestDict.has_key('CacheSizeTuple'):
					CacheSizeTuple = RequestDict['CacheSizeTuple']			
				#self._lockDb(sPath, sEnvName)
				#print 'open', sPath, sMode
				if sMode == 'w':
					if self.server.DataDict['path_info'].has_key(sPath):
						iDbId = self.server.DataDict['path_info'][sPath][0][0]
					else:
						iDbId = random.randint(0, 999999)
						while self.server.DataDict['db'].has_key(iDbId):
							iDbId = random.randint(0, 999999)
				else:
					iDbId = random.randint(0, 999999)
					while self.server.DataDict['db'].has_key(iDbId):
						iDbId = random.randint(0, 999999)
				#print 'iDbId->', iDbId
				#print self.server.DataDict
				#print 'sEnvName=>', sEnvName
				if sEnvName:
					oDbEnv = self.server.DataDict['env'][sEnvName]
					#print oDbEnv
					self.server.DataDict['db'][iDbId] = db.DB(oDbEnv)
				else:
					self.server.DataDict['db'][iDbId] = db.DB()
				#print 'Flags=>', 'Add->', iFlagsAdd, 'Open->', iFlagsOpen, 'CacheSizeTuple->', CacheSizeTuple
				if CacheSizeTuple[0] != 0 or CacheSizeTuple[1] != 0:
					self.server.DataDict['db'][iDbId].set_cachesize(CacheSizeTuple[0], CacheSizeTuple[1])
				if iFlagsAdd != 0:
					#print 'I set duplicates'
					self.server.DataDict['db'][iDbId].set_flags(iFlagsAdd)
				path = RequestDict['sPath']
				#print 'path=', path, 'DbName->', sDbName, 'iDbType->', iDbType, 'iFlagsOpen->', iFlagsOpen, 'iFileMode->', iFileMode, 'iTxn->', iTxn
				#print 'iDbId->', iDbId
			
				# BUG: When user does not exist and not set db.DB_CREATE the open() method hangs
			 
			 	# Open data file
				self.server.DataDict['db'][iDbId].open(path, sDbName, iDbType, iFlagsOpen, iFileMode, iTxn)

				self.server.DataDict['db_info'][iDbId] = [sPath, sEnvName, []]
				if self.server.DataDict['path_info'].has_key(sPath):
					DbList, CursorList, ReadWriteDbList = self.server.DataDict['path_info'][sPath]
					if iDbId not in DbList:
						DbList.append(iDbId)
					if sMode == 'w':
						#if iDbId not in ReadWriteDbList[1]:
						ReadWriteDbList[1].append(iDbId)
					else:
						if iDbId not in ReadWriteDbList[0]:
							ReadWriteDbList[0].append(iDbId)
					self.server.DataDict['path_info'][sPath] = [DbList, CursorList, ReadWriteDbList]
				else:
					if sMode == 'w':
						ReadWriteDbList = ([],[iDbId])
					else:
						ReadWriteDbList = ([iDbId],[])
					self.server.DataDict['path_info'][sPath] = [[iDbId], [], ReadWriteDbList]
			except db.DBNoSuchFileError:
				if self.server.DataDict['db'].has_key(iDbId):
					del self.server.DataDict['db'][iDbId]
				raise
			except db.DBInvalidArgError:
				if self.server.DataDict['db'].has_key(iDbId):
					del self.server.DataDict['db'][iDbId]
				raise
			except:
				# Delete iDbId
				if self.server.DataDict['db'].has_key(iDbId):
					del self.server.DataDict['db'][iDbId]
				raise
			finally:
				self.ThreadLock.release()
			ResponseDict['List'] = [iDbId]
			ResponseDict['bResult'] = True
			#self._unlockDb(sPath)
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _close(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'close'
			bLock = self.ThreadLock.acquire()
			try:
				#self._lockDb(sPath, sEnvName)
				#print self.server.DataDict['db_info']
				sEnvName = RequestDict['sEnvName']
				sMode = RequestDict['sMode']
				if self.server.DataDict['db_info'].has_key(iDbId):
					DbInfoTuple = self.server.DataDict['db_info'][iDbId]
					sPath, sEnvName, CursorDbList = DbInfoTuple
				if self.server.DataDict['db'].has_key(iDbId):
					CloseCursorDict = {}
					PathInfoTuple = self.server.DataDict['path_info'][sPath]
					DbList, CursorList, ReadWriteDbList = PathInfoTuple
					if sMode == 'r' and iDbId not in ReadWriteDbList[1]:
						# only read open table
						DbList.remove(iDbId)
						ReadWriteDbList[0].remove(iDbId)
					elif sMode == 'r' and iDbId in ReadWriteDbList[1]:
						# both read and write open tables, we opened as read
						ReadWriteDbList[0].remove(iDbId)
					elif sMode == 'w' and iDbId not in ReadWriteDbList[0]:
						# only write open table, we open as write
						ReadWriteDbList[1].remove(iDbId)
						if len(ReadWriteDbList[1]) == 0:
							DbList.remove(iDbId)
					elif sMode == 'w' and iDbId in ReadWriteDbList[0]:
						# both read and write open tables, we opened as write
						ReadWriteDbList[1].remove(iDbId)
					if len(DbList) == 0:
						# No open files
						for cursor in CursorList:
							CloseCursorDict[cursor] = ''
						del self.server.DataDict['path_info'][sPath]
					else:
						# Still opened files
						for cursor in CursorList:
							if cursor in CursorDbList:
								CloseCursorDict[cursor] = ''
								CursorList.remove(cursor)
						self.server.DataDict['path_info'][sPath] = [DbList, CursorList, ReadWriteDbList]
					for cursor in CursorDbList:
						CloseCursorDict[cursor] = ''
					# Process cursors
					if iDbId not in ReadWriteDbList[1] and iDbId not in ReadWriteDbList[0]:
						for cursor in CloseCursorDict:
							cursor.close()
						del self.server.DataDict['db_info'][iDbId]
						self.server.DataDict['db'][iDbId].close()
						del self.server.DataDict['db'][iDbId]
				#print self.server.DataDict
				ResponseDict['bResult'] = True
				#self._unlockDb(sPath)
			except:					
				raise
			finally:
				self.ThreadLock.release()
		else:
			self._waitForUnlock()
		return ResponseDict
	def _hasKey(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'has_key'
			sName = RequestDict['sName']
			if self.server.DataDict['db'][iDbId].has_key(sName):
				bExists = True
			else:
				bExists = False
			ResponseDict['bResult'] = True
			ResponseDict['List'] = [bExists]
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _put(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'put'
			DbInfoTuple = self.server.DataDict['db_info'][iDbId]
			sPath, sEnvName, CursorDbList = DbInfoTuple
			self._lockDb(sPath, sEnvName)
			sName = RequestDict['sName']
			sValue = RequestDict['sValue']
			self.server.DataDict['db'][iDbId].put(sName, sValue)
			ResponseDict['bResult'] = True
			self._unlockDb(sPath)
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _get(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'get'
			sName = RequestDict['sName']
			sValue = self.server.DataDict['db'][iDbId].get(sName)
			ResponseDict['bResult'] = True
			ResponseDict['List'] = [sValue]
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _putList(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'putList'
			DbInfoTuple = self.server.DataDict['db_info'][iDbId]
			sPath, sEnvName, CursorDbList = DbInfoTuple
			self._lockDb(sPath, sEnvName)
			DataList = RequestDict['DataList']
			for Tuple in DataList:
				sName, sValue = Tuple
				self.server.DataDict['db'][iDbId].put(str(sName), str(sValue))
			ResponseDict['bResult'] = True
			self._unlockDb(sPath)
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _getList(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'getList'
			DataList = RequestDict['NameList']
			for sName in DataList:
				sValue = self.server.DataDict['db'][iDbId].get(str(sName))
				Tuple = (sName, sValue)
				ResponseDict['List'].append(Tuple)
			ResponseDict['bResult'] = True
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _checkList(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'checkList'
			DataList = RequestDict['NameList']
			for sName in DataList:
				bValueTmp = self.server.DataDict['db'][iDbId].has_key(str(sName))
				if bValueTmp:
					bValue = True
				else:
					bValue = False
				Tuple = (sName, bValue)
				ResponseDict['List'].append(Tuple)
				ResponseDict['bResult'] = True
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _keys(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'keys'
			ResponseDict['List'] = self.server.DataDict['db'][iDbId].keys()
			ResponseDict['bResult'] = True
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _values(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'values'
			ResponseDict['List'] = self.server.DataDict['db'][iDbId].values()
			ResponseDict['bResult'] = True
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _items(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'items'
			ResponseDict['List'] = self.server.DataDict['db'][iDbId].items()
			ResponseDict['bResult'] = True
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _delete(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'delete'
			DbInfoTuple = self.server.DataDict['db_info'][iDbId]
			sPath, sEnvName, CursorDbList = DbInfoTuple
			self._lockDb(sPath, sEnvName)
			sName = RequestDict['sName']
			self.server.DataDict['db'][iDbId].delete(sName)
			ResponseDict['bResult'] = True
			self._unlockDb(sPath)
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _stat(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'stat'
			Dict = self.server.DataDict['db'][iDbId].stat()
			ResponseDict['List'] = [Dict]
			ResponseDict['bResult'] = True
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _sync(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'sync'
			DbInfoTuple = self.server.DataDict['db_info'][iDbId]
			sPath, sEnvName, CursorDbList = DbInfoTuple
			self._lockDb(sPath, sEnvName)
			self.server.DataDict['db'][iDbId].sync()
			ResponseDict['bResult'] = True
			self._unlockDb(sPath)
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _truncate(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'truncate'
			DbInfoTuple = self.server.DataDict['db_info'][iDbId]
			sPath, sEnvName, CursorDbList = DbInfoTuple
			self._lockDb(sPath, sEnvName)
			self.server.DataDict['db'][iDbId].truncate()
			ResponseDict['bResult'] = True
			self._unlockDb(sPath)
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _getDirect(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		#print 'getDirect()'
		if self.server.DataDict['lock'] == False:			
			sName = RequestDict['sName']
			try:
				ResponseOpenDict = self._open(iDbId, RequestDict, ResponseDict)
				iDbId = int(ResponseOpenDict['List'][0])
				sValue = self.server.DataDict['db'][iDbId].get(sName)
				ResponseDict['bResult'] = True
				ResponseDict['List'] = [sValue]
				ResponseCloseDict = self._close(iDbId, RequestDict, ResponseDict)
			except db.DBNoSuchFileError:
				ResponseDict['bResult'] = False
				ResponseDict['List'] = [None]
				raise
		else:
			self._waitForUnlock()
		return ResponseDict
	def _getListDirect(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:			
			DataList = RequestDict['NameList']
			try:
				ResponseOpenDict = self._open(iDbId, RequestDict, ResponseDict)
				iDbId = int(ResponseOpenDict['List'][0])
				ResponseDict['List'] = []
				for sName in DataList:
					sValue = self.server.DataDict['db'][iDbId].get(str(sName))
					Tuple = (sName, sValue)
					ResponseDict['List'].append(Tuple)
				ResponseDict['bResult'] = True
				ResponseCloseDict = self._close(iDbId, RequestDict, ResponseDict)
			except db.DBNoSuchFileError:
				ResponseDict['bResult'] = False
				ResponseDict['List'] = [None]
				raise
			except:
				ResponseDict['bResult'] = False
				ResponseDict['List'] = [None]
				raise
		else:
			self._waitForUnlock()
		return ResponseDict
	def _putDirect(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:			
			sName = RequestDict['sName']
			sValue = RequestDict['sValue']
			sPath = RequestDict['sPath']
			sEnvName = RequestDict['sEnvName']
			self._lockDb(sPath, sEnvName)
			try:
				ResponseOpenDict = self._open(iDbId, RequestDict, ResponseDict)
			except db.DBNoSuchFileError:
				raise
			except:
				raise
			iDbId = int(ResponseOpenDict['List'][0])
			try:
				self.server.DataDict['db'][iDbId].put(sName, sValue)
				ResponseDict['bResult'] = True
			except:
				if RequestDict.has_key('bResponse') and RequestDict['bResponse']:
					# Expects response
					raise
				else:
					ResponseDict['bResult'] = False
					sText = sPath + ': ' + 'putDirect' + '()' + ' => ' + sName + ', ' + sValue
					#self._lockDb(self.__PATH_ERROR_DETAIL, sEnvName)
					oLog = Log()
					oLog.open(self.__PATH_ERROR_DETAIL, 'w')
					oLog.write(sText)
					oLog.close()					
					#self._unlockDb(self.__PATH_ERROR_DETAIL)
			ResponseCloseDict = self._close(iDbId, RequestDict, ResponseDict)
			self._unlockDb(sPath)
		else:
			self._waitForUnlock()
		return ResponseDict
	def _putListDirect(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:			
			DataList = RequestDict['DataList']
			sPath = RequestDict['sPath']
			sEnvName = RequestDict['sEnvName']
			self._lockDb(sPath, sEnvName)
			try:
				ResponseOpenDict = self._open(iDbId, RequestDict, ResponseDict)
			except db.DBNoSuchFileError:
				raise
			iDbId = int(ResponseOpenDict['List'][0])
			for Tuple in DataList:
				sName, sValue = Tuple
				#print 'Data->', sName, sValue
				try:
					self.server.DataDict['db'][iDbId].put(str(sName), str(sValue))
					ResponseDict['bResult'] = True
				except:
					if RequestDict.has_key('bResponse') and RequestDict['bResponse']:
						# Expects response
						raise
					else:
						ResponseDict['bResult'] = False
						sText = sPath + ': ' + 'putListDirect' + '()' + ' => ' + sName + ', ' + sValue
						#self._lockDb(self.__PATH_ERROR_DETAIL, sEnvName)
						oLog = Log()
						oLog.open(self.__PATH_ERROR_DETAIL, 'w')
						oLog.write(sText)
						oLog.close()					
						#self._unlockDb(self.__PATH_ERROR_DETAIL)
			ResponseCloseDict = self._close(iDbId, RequestDict, ResponseDict)
			self._unlockDb(sPath)
		else:
			self._waitForUnlock()
		return ResponseDict
	def _cursor(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'cursor'
			#print 'iDbId->', iDbId
			bLock = self.ThreadLock.acquire()
			try:
				DbInfoTuple = self.server.DataDict['db_info'][iDbId]
				sPath, sEnvName, CursorDbList = DbInfoTuple
				iCursor = random.randint(0, 999999)
				while self.server.DataDict['c'].has_key(iCursor):
					iCursor = random.randint(0, 999999)
				cursor = self.server.DataDict['db'][iDbId].cursor()
				self.server.DataDict['c'][iCursor] = cursor
				self.server.DataDict['db_info'][iDbId][2].append(cursor)
				self.server.DataDict['path_info'][sPath][1].append(cursor)
				#print self.server.DataDict
				ResponseDict['List'] = [iCursor]
				ResponseDict['bResult'] = True
			except:
				# Delete iDbId
				if iCursor and self.server.DataDict['c'].has_key(iCursor):
					cursor = self.server.DataDict['c'][iCursor]					
					if self.server.DataDict['db_info'].has_key(iDbId):
						DbInfoTuple = self.server.DataDict['db_info'][iDbId]
						sPath, sEnvName, CursorDbList = DbInfoTuple
						CloseCursorDict = {}
						CloseCursorDict[cursor] = ''
						if sPath and self.server.DataDict['path_info'].has_key(sPath):
							CursorList = self.server.DataDict['path_info'][sPath][1]
							if cursor in CursorList:
								self.server.DataDict['path_info'][sPath][1].remove(cursor)
						if cursor in CursorDbList:
							self.server.DataDict['db_info'][iDbId][2].remove(cursor)
						for cursor in CloseCursorDict:
							cursor.close()
					del self.server.DataDict['c'][iCursor]
				raise
			finally:
				self.ThreadLock.release()
		else:
			self._waitForUnlock()
		return ResponseDict
	def _cursorFirst(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'cursor.first'
			ArgsTuple = RequestDict['ArgsTuple']
			iCursor = RequestDict['iCursor']
			Tuple = self.server.DataDict['c'][iCursor].first(*ArgsTuple)
			ResponseDict['List'] = [Tuple]
			ResponseDict['bResult'] = True
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _cursorNext(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'cursor.next'
			ArgsTuple = RequestDict['ArgsTuple']
			iCursor = RequestDict['iCursor']
			Tuple = self.server.DataDict['c'][iCursor].next(*ArgsTuple)
			ResponseDict['bResult'] = True
			ResponseDict['List'] = [Tuple]
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _cursorFirstList(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'cursor.firstList'
			iCursor = RequestDict['iCursor']
			ArgsTuple = RequestDict['ArgsTuple']
			Tuple = self.server.DataDict['c'][iCursor].first(*ArgsTuple)
			if Tuple:
				ResponseDict['List'].append(Tuple)
				iRows = RequestDict['iRows']-1
				for i in range(iRows):
					Tuple = self.server.DataDict['c'][iCursor].next()
					if Tuple:
						ResponseDict['List'].append(Tuple)
					else:
						break
			ResponseDict['bResult'] = True
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _cursorNextList(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'cursor.nextList'
			iCursor = RequestDict['iCursor']
			iRows = RequestDict['iRows']
			ArgsTuple = RequestDict['ArgsTuple']
			for i in range(iRows):
				Tuple = self.server.DataDict['c'][iCursor].next(*ArgsTuple)
				if Tuple:
					ResponseDict['List'].append(Tuple)
				else:
					break
			ResponseDict['bResult'] = True
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _cursorFirstDupList(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'cursor.firstDupList'
			iCursor = RequestDict['iCursor']
			ArgsTuple = RequestDict['ArgsTuple']
			sName = RequestDict['sName']
			Tuple = self.server.DataDict['c'][iCursor].set(sName)
			iRows = RequestDict['iRows']-1
			if Tuple:
				ResponseDict['List'].append(Tuple)
				for i in range(iRows):
					Tuple = self.server.DataDict['c'][iCursor].next_dup()
					if Tuple:
						ResponseDict['List'].append(Tuple)
					else:
						# Should break for loop
						break
			ResponseDict['bResult'] = True
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _cursorCheckDupKey(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'cursor.checkDupKey'
			iCursor = RequestDict['iCursor']
			sName = RequestDict['sName']
			sValue = RequestDict['sValue']
			bExists = False
			Tuple = self.server.DataDict['c'][iCursor].set(sName)
			while Tuple:
				sNameTarget, sValueTarget = Tuple
				if sName == sNameTarget and sValue == sValueTarget:
					bExists = True
				Tuple = self.server.DataDict['c'][iCursor].next_dup()
			ResponseDict['bResult'] = True
			ResponseDict['List'] = [bExists]
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _cursorDeleteDupKey(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'cursor.deleteDupKey'
			DbInfoTuple = self.server.DataDict['db_info'][iDbId]
			sPath, sEnvName, CursorDbList = DbInfoTuple
			self._lockDb(sPath, sEnvName)
			iCursor = RequestDict['iCursor']
			sName = RequestDict['sName']
			sValue = RequestDict['sValue']
			Tuple = self.server.DataDict['c'][iCursor].set(sName)
			while Tuple:
				sNameTarget, sValueTarget = Tuple
				if sName == sNameTarget and sValue == sValueTarget:
					self.server.DataDict['c'][iCursor].delete()
					Tuple = self.server.DataDict['c'][iCursor].next_dup()
					#print 'Tuple Delete=>', Tuple
				Tuple = self.server.DataDict['c'][iCursor].next_dup()
			ResponseDict['bResult'] = True
			self._unlockDb(sPath)
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _cursorPrevList(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'cursor.prevList'
			iCursor = RequestDict['iCursor']
			iRows = RequestDict['iRows']
			ArgsTuple = RequestDict['ArgsTuple']
			# pur cursor at previous set
			for i in range((iRows*2)-1):
				Tuple = self.server.DataDict['c'][iCursor].prev(*ArgsTuple)
				if Tuple:
					TupleFirst = Tuple
			ResponseDict['List'].append(TupleFirst)
			for i in range(iRows-1):
				Tuple = self.server.DataDict['c'][iCursor].next(*ArgsTuple)
				if Tuple:
					ResponseDict['List'].append(Tuple)
			ResponseDict['bResult'] = True
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _cursorNextDupList(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'cursor.nextDupList'
			iCursor = RequestDict['iCursor']
			iRows = RequestDict['iRows']
			ArgsTuple = RequestDict['ArgsTuple']
			for i in range(iRows):
				Tuple = self.server.DataDict['c'][iCursor].next_dup(*ArgsTuple)
				if Tuple:
					ResponseDict['List'].append(Tuple)
				else:
					break
			ResponseDict['bResult'] = True
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _cursorGetDupList(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'cursor.getDupList'
			iCursor = RequestDict['iCursor']
			sName = RequestDict['sName']
			TupleList = []
			Tuple = self.server.DataDict['c'][iCursor].set(sName)
			while Tuple:
				TupleList.append(Tuple)
				Tuple = self.server.DataDict['c'][iCursor].next_dup()
			ResponseDict['bResult'] = True
			ResponseDict['List'] = TupleList
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _cursorNextNoDupList(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'cursor.nextNoDupList'
			iCursor = RequestDict['iCursor']
			iRows = RequestDict['iRows']
			ArgsTuple = RequestDict['ArgsTuple']
			for i in range(iRows):
				Tuple = self.server.DataDict['c'][iCursor].next_nodup(*ArgsTuple)
				if Tuple:
					ResponseDict['List'].append(Tuple)
				else:
					break
			ResponseDict['bResult'] = True
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _cursorPrev(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'cursor.prev'
			iCursor = RequestDict['iCursor']
			ArgsTuple = RequestDict['ArgsTuple']
			Tuple = self.server.DataDict['c'][iCursor].prev(*ArgsTuple)
			ResponseDict['List'] = [Tuple]
			ResponseDict['bResult'] = True
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _cursorPrevNoDup(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'cursor.prev_nodup'
			iCursor = RequestDict['iCursor']
			ArgsTuple = RequestDict['ArgsTuple']
			Tuple = self.server.DataDict['c'][iCursor].prev_nodup(*ArgsTuple)
			ResponseDict['List'] = [Tuple]
			ResponseDict['bResult'] = True
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _cursorSet(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'cursor.set'
			iCursor = RequestDict['iCursor']
			sName = RequestDict['sName']
			ArgsTuple = RequestDict['ArgsTuple']
			Tuple = self.server.DataDict['c'][iCursor].set(sName, *ArgsTuple)
			ResponseDict['List'] = [Tuple]
			ResponseDict['bResult'] = True
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _cursorSetList(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'cursor.setList'
			iCursor = RequestDict['iCursor']
			sName = RequestDict['sName']
			iRows = RequestDict['iRows']
			sMode = RequestDict['sMode']
			ArgsTuple = RequestDict['ArgsTuple']
			TupleList = []
			Tuple = self.server.DataDict['c'][iCursor].set(sName, *ArgsTuple)
			if Tuple:
				while len(TupleList) != iRows:
					TupleList.append(Tuple)
					if sMode == 'dup':
						Tuple = self.server.DataDict['c'][iCursor].next_dup()
					else:
						Tuple = self.server.DataDict['c'][iCursor].next()
					if not Tuple:
						break
				ResponseDict['List'] = TupleList
				ResponseDict['bResult'] = True
			else:
				ResponseDict['List'] = None
				ResponseDict['bResult'] = True
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _cursorNextDup(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'cursor.next_dup'
			iCursor = RequestDict['iCursor']
			ArgsTuple = RequestDict['ArgsTuple']
			Tuple = self.server.DataDict['c'][iCursor].next_dup(*ArgsTuple)
			ResponseDict['List'] = [Tuple]
			ResponseDict['bResult'] = True
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _cursorNextNoDup(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'cursor.next_nodup'
			iCursor = RequestDict['iCursor']
			ArgsTuple = RequestDict['ArgsTuple']
			Tuple = self.server.DataDict['c'][iCursor].next_nodup(*ArgsTuple)
			ResponseDict['List'] = [Tuple]
			ResponseDict['bResult'] = True
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _cursorLast(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'cursor.last'
			iCursor = RequestDict['iCursor']
			ArgsTuple = RequestDict['ArgsTuple']
			Tuple = self.server.DataDict['c'][iCursor].last(*ArgsTuple)
			ResponseDict['List'] = [Tuple]
			ResponseDict['bResult'] = True
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _cursorCount(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'cursor.count'
			iCursor = RequestDict['iCursor']
			ArgsTuple = RequestDict['ArgsTuple']
			iCount = self.server.DataDict['c'][iCursor].count(*ArgsTuple)
			ResponseDict['List'] = [iCount]
			ResponseDict['bResult'] = True
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _cursorDelete(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'cursor.delete'
			DbInfoTuple = self.server.DataDict['db_info'][iDbId]
			sPath, sEnvName, CursorDbList = DbInfoTuple
			self._lockDb(sPath, sEnvName)
			iCursor = RequestDict['iCursor']
			ArgsTuple = RequestDict['ArgsTuple']
			self.server.DataDict['c'][iCursor].delete(*ArgsTuple)
			ResponseDict['bResult'] = True
			self._unlockDb(sPath)
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _cursorPut(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'cursor.put'
			DbInfoTuple = self.server.DataDict['db_info'][iDbId]
			sPath, sEnvName, CursorDbList = DbInfoTuple
			self._lockDb(sPath, sEnvName)
			iCursor = RequestDict['iCursor']
			sName = RequestDict['sName']
			sValue = RequestDict['sValue']
			ArgsTuple = RequestDict['ArgsTuple']
			self.server.DataDict['c'][iCursor].put(sName, sValue, *ArgsTuple)
			ResponseDict['bResult'] = True
			self._unlockDb(sPath)
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _cursorCurrent(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'cursor.current'
			iCursor = RequestDict['iCursor']
			ArgsTuple = RequestDict['ArgsTuple']
			Tuple = self.server.DataDict['c'][iCursor].current(*ArgsTuple)
			ResponseDict['List'] = [Tuple]
			ResponseDict['bResult'] = True
			#print self.server.DataDict
		return ResponseDict
	def _cursorClose(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		if self.server.DataDict['lock'] == False:
			#print 'cursor.close'
			bLock = self.ThreadLock.acquire()
			try:
				DbInfoTuple = self.server.DataDict['db_info'][iDbId]
				sPath, sEnvName, CursorDbList = DbInfoTuple
				iCursor = RequestDict['iCursor']
				cursor = self.server.DataDict['c'][iCursor]
				CloseCursorDict = {}
				CloseCursorDict[cursor] = ''
				CursorList = self.server.DataDict['path_info'][sPath][1]
				if cursor in CursorList:
					self.server.DataDict['path_info'][sPath][1].remove(cursor)
				if cursor in CursorDbList:
					self.server.DataDict['db_info'][iDbId][2].remove(cursor)
				for cursor in CloseCursorDict:
					cursor.close()
				del self.server.DataDict['c'][iCursor]
				ResponseDict['bResult'] = True
			except:
				if self.server.DataDict['db'].has_key(iDbId):
					del self.server.DataDict['db'][iDbId]
				if iCursor and self.server.DataDict['c'].has_key(iCursor):
					del self.server.DataDict['c'][iCursor]
				if self.server.DataDict['db_info'].has_key(iDbId):
					del self.server.DataDict['db_info'][iDbId]
				if sPath and self.server.DataDict['path_info'].has_key(sPath):
					del self.server.DataDict['path_info'][sPath]
				raise
			finally:
				self.ThreadLock.release()
			#print self.server.DataDict
		else:
			self._waitForUnlock()
		return ResponseDict
	def _search(self, iDbId, RequestDict, ResponseDict):
		"""@param iDbId: id for database table
		@param RequestDict: Dictionary for request
		@param ResponseDict: Dictionary for response
		@return: ResponseDict"""
		#print 'search()'
		if self.server.DataDict['lock'] == False:
			try:
				#print 'open()' 
				ResponseOpenDict = self._open(iDbId, RequestDict, ResponseDict)
				iDbId = int(ResponseOpenDict['List'][0])
				ResponseCursorDict = self._cursor(iDbId, RequestDict, ResponseDict)
				iCursor = int(ResponseCursorDict['List'][0])
				RequestDict['iCursor'] = iCursor
				ResponseDict['List'] = []
				NameList = RequestDict['NameList']
				for sName in NameList:
					RequestDict['sName'] = sName.encode(self.__ENCODING)
					ResponseDict = self._cursorFirstDupList(iDbId, RequestDict, ResponseDict)
				ResponseDict['bResult'] = True
				ResponseCursorCloseDict = self._cursorClose(iDbId, RequestDict, ResponseDict)
				ResponseCloseDict = self._close(iDbId, RequestDict, ResponseDict)
				#print 'close()'
			except db.DBNoSuchFileError:
				ResponseDict['bResult'] = False
				ResponseDict['List'] = [None]
				raise
		else:
			self._waitForUnlock()
		return ResponseDict
	def _getListDirectMulti(self, iDbId, RequestDict, ResponseDict):
		"""Get list of values from different files
		@param iDbId: id for Data file in server
		@param RequestDict: Request
		@param ResponseDict: Response
		@return: ResponseDict : Response"""
		if self.server.DataDict['lock'] == False:			
			EnDataList = RequestDict['DataList']
			ResponseDict['List'] = []
			for EnData in EnDataList:
				NameList = EnData.NameList
				ResponseOpenDict = {}
				ResponseCloseDict = {}
				RequestDict['sPath'] = EnData.Path
				EnData.ValueList = []
				try:
					ResponseOpenDict = self._open(iDbId, RequestDict, ResponseOpenDict)
					iDbId = int(ResponseOpenDict['List'][0])
					for sName in NameList:
						sValue = self.server.DataDict['db'][iDbId].get(str(sName))							
						EnData.ValueList.append((sName, sValue))
					ResponseDict['List'].append(EnData)
					ResponseDict['bResult'] = True
					ResponseCloseDict = self._close(iDbId, RequestDict, ResponseCloseDict)
				except db.DBNoSuchFileError:
					ResponseDict['bResult'] = False
					ResponseDict['List'].append(None)
					raise
				except:
					ResponseDict['bResult'] = False
					ResponseDict['List'].append(None)
					raise
		else:
			self._waitForUnlock()
		return ResponseDict
	def _putListDirectMulti(self, iDbId, RequestDict, ResponseDict):
		"""Doc."""
		if self.server.DataDict['lock'] == False:
			EnDataList = RequestDict['DataList']
			ResponseDict['List'] = []
			for EnData in EnDataList:
				NameList = []
				sPath = EnData.Path
				ResponseOpenDict = {}
				ResponseCloseDict = {}
				RequestDict['sPath'] = EnData.Path
				ValueList = EnData.ValueList 
				try:
					ResponseOpenDict = self._open(iDbId, RequestDict, ResponseOpenDict)
					iDbId = int(ResponseOpenDict['List'][0])
					for tuple in ValueList:
						if type(tuple) == types.TupleType:
							sName, sValue = tuple
							self.server.DataDict['db'][iDbId].put(str(sName), str(sValue))
					ResponseDict['bResult'] = True
					ResponseCloseDict = self._close(iDbId, RequestDict, ResponseCloseDict)
				except db.DBNoSuchFileError:
					ResponseDict['bResult'] = False
					sText = sPath + ': ' + 'putListDirectMulti' + '()'
					oLog = Log()
					oLog.open(self.__PATH_ERROR_DETAIL, 'w')
					oLog.write(sText)
					oLog.close()
					raise
				except:
					ResponseDict['bResult'] = False
					sText = sPath + ': ' + 'putListDirectMulti' + '()'
					oLog = Log()
					oLog.open(self.__PATH_ERROR_DETAIL, 'w')
					oLog.write(sText)
					oLog.close()
					raise
		else:
			self._waitForUnlock()
		return ResponseDict
	def _doDb(self, RequestDict):
		sOp = RequestDict['sOp']
		iDbId = RequestDict['iDbId']
		ResponseDict = {}
		ResponseDict['bResult'] = False
		ResponseDict['List'] = []
		ResponseDict['sError'] = None
		#print 'ResponseDict->', ResponseDict, sOp, iDbId
		OpDict = {}
		OpDict['open'] = self._open
		OpDict['cursor'] = self._cursor
		OpDict['cursor.close'] = self._cursorClose
		OpDict['close'] = self._close
		OpDict['has_key'] = self._hasKey
		OpDict['put'] = self._put
		OpDict['get'] = self._get
		OpDict['putList'] = self._putList
		OpDict['getList'] = self._getList
		OpDict['checkList'] = self._checkList
		OpDict['keys'] = self._keys
		OpDict['values'] = self._values
		OpDict['items'] = self._items
		OpDict['delete'] = self._delete
		OpDict['stat'] = self._stat
		OpDict['sync'] = self._sync
		OpDict['truncate'] = self._truncate
		OpDict['getDirect'] = self._getDirect
		OpDict['getListDirect'] = self._getListDirect
		OpDict['getListDirectMulti'] = self._getListDirectMulti
		OpDict['putDirect'] = self._putDirect
		OpDict['putListDirect'] = self._putListDirect
		OpDict['putListDirectMulti'] = self._putListDirectMulti
		OpDict['search'] = self._search
		OpDict['cursor.first'] = self._cursorFirst
		OpDict['cursor.next'] = self._cursorNext
		OpDict['cursor.firstList'] = self._cursorFirstList
		OpDict['cursor.nextList'] = self._cursorNextList
		OpDict['cursor.firstDupList'] = self._cursorFirstDupList
		OpDict['cursor.checkDupKey'] = self._cursorCheckDupKey
		OpDict['cursor.deleteDupKey'] = self._cursorDeleteDupKey
		OpDict['cursor.prevList'] = self._cursorPrevList
		OpDict['cursor.nextDupList'] = self._cursorNextDupList
		OpDict['cursor.getDupList'] = self._cursorGetDupList
		OpDict['cursor.nextNoDupList'] = self._cursorNextNoDupList
		OpDict['cursor.prev'] = self._cursorPrev
		OpDict['cursor.prev_nodup'] = self._cursorPrevNoDup
		OpDict['cursor.set'] = self._cursorSet
		OpDict['cursor.setList'] = self._cursorSetList
		OpDict['cursor.next_dup'] = self._cursorNextDup
		OpDict['cursor.next_nodup'] = self._cursorNextNoDup
		OpDict['cursor.last'] = self._cursorLast
		OpDict['cursor.count'] = self._cursorCount
		OpDict['cursor.delete'] = self._cursorDelete
		OpDict['cursor.put'] = self._cursorPut
		OpDict['cursor.current'] = self._cursorCurrent
		try:
			ResponseDict = OpDict[sOp](iDbId, RequestDict, ResponseDict)
		except:
			sErrMsg = traceback.format_exc() 
			ResponseDict['bResult'] = False
			ResponseDict['sError'] = sErrMsg
			sDate = time.strftime('%d/%m/%Y %H:%M')
			self.fd.write('[' + sDate + ']' + sErrMsg)
		return ResponseDict
	def _toStrDict(self, DictTmp):
		Dict = {}
		for Key in DictTmp.keys():
			value = DictTmp[Key]
			if type(value) == types.UnicodeType:
				Dict[str(Key)] = str(DictTmp[Key])
			else:
				Dict[str(Key)] = DictTmp[Key]
		return Dict
	def handle(self):
		fd = open(self.__PATH_ERROR, 'a')
		self.fd = fd
		sys.stderr = fd
		SocketRequest = self.request
		DataList = []
		returnCode = 'ok'
		BUFFER = 16384
		#BUFFER = 64
		BUFFER_FIRST = 332
		dataFirst = SocketRequest.recv(BUFFER_FIRST)
		dataFirst = dataFirst.replace('\r\n', '')
		Fields = dataFirst.split(';')
		#print 'Fields=>', Fields
		bValidation = False
		sPathUserAuth = 'users.db'
		sPathEnvAuth = 'env.db'
		if len(Fields) == 3:
			sUser = Fields[0].strip()
			sPassword = Fields[1].strip()
			sEnvName = Fields[2].strip()
			if sUser!= '' and sPassword != '':
				bValidation = True
		bPasswordAuth = False
		bEnvAuth = False
		DbEnv = self.server.DataDict['env']['octopusdbm']
		#print 'bValidation=>', bValidation
		Dict = {}
		if bValidation:
			# Password Auth
			#print 'Password Auth'
			dbm = db.DB(DbEnv)
			dbm.open(sPathUserAuth)
			sPasswordDisk = dbm.get(sUser)
			if sPasswordDisk:
				if sPasswordDisk == sPassword:
					bPasswordAuth = True
			dbm.close()
			# Env Auth
			#print 'env auth'
			if sUser == self.__SYS_ACCOUNT:
				bEnvAuth = True
			else:
				dbm = db.DB(DbEnv)
				dbm.open(sPathEnvAuth)
				c = dbm.cursor()
				Tuple = c.set(sUser)
				while Tuple:
					sEnvDisk = Tuple[1]
					if sEnvDisk == sEnvName:
						bEnvAuth = True
					Tuple = c.next_dup()
				c.close()
				dbm.close()
			#print 'auth=>', bPasswordAuth, bEnvAuth
			#print 'password=>', sPasswordDisk, sPassword
			if bPasswordAuth and bEnvAuth:
				while 1:
					data = SocketRequest.recv(BUFFER)
					DataList.append(data)
					try:
						SDict = string.joinfields(DataList, '')
						#Dict = jsonpickle.decode(SDict)
						Dict = cPickle.loads(SDict)
						#print 'JsON->', SDict
						#Dict = json.loads(SDict)
						break
					except EOFError:
						pass
					except cPickle.UnpicklingError:
						pass
					except socket.error:
						returnCode = 'error'
					except ValueError:
						pass
					
		#RequestDict = self._toStrDict(Dict)
		#RequestDict = self.__toStringDict(Dict)
		RequestDict = Dict
		#print 'RequestDict=>', RequestDict
		ResponseDict = {}
		if len(RequestDict) != 0:
			##print 'RequestDict=', RequestDict
			sEnvName = RequestDict['sEnvName']
			sOp = RequestDict['sOp']
			if sOp == 'closeEnv':
				self.server.DataDict['lock'] = True
				List = self.server.DataDict['c'].keys()
				i = 0
				while i != len(List):
					try:
						self.server.DataDict['c'][List[i]].close()
						del self.server.DataDict['c'][List[i]]
					except:
						pass
					i = i + 1
				List = self.server.DataDict['db'].keys()
				i = 0
				while i != len(List):
					try:
						self.server.DataDict['db'][List[i]].close()
						del self.server.DataDict['db'][List[i]]
					except:
						pass
					i = i + 1
				self.server.DataDict['env'][sEnvName].close()
				del self.server.DataDict['env'][sEnvName]
				del self.server.DataDict['env_path'][sEnvName]
				ResponseDict['bResult'] = True
				self.server.DataDict['lock'] = False
				#print self.server.DataDict
			elif sOp == 'getDataDict':
				Dict = self.server.DataDict 
				ResponseDict['bResult'] = True
				OutDict = {}
				OutDict['lock'] = Dict['lock']
				TupleList = []
				PathList = Dict['path_info'].keys()
				#self.server.DataDict['path_info'][sPath] = [DbList, CursorList, ReadWriteDbList]
				for sPath in PathList:
					List = Dict['path_info'][sPath]
					DbList, CursorList, ReadWriteDbList = List
					sDbList = []
					for iDbId in DbList:
						sDbList.append(str(iDbId))
					SDbList = ','.join(sDbList)
					TupleList.append((sPath, SDbList))
				OutDict['path'] = TupleList
				sOutDict = str(OutDict)
				ResponseDict['List'] = [sOutDict]
			elif sOp == 'reOpenAll':
				self.server.DataDict['lock'] = True
				List = self.server.DataDict['c'].keys()
				i = 0
				while i != len(List):
					try:
						self.server.DataDict['c'][List[i]].close()
						del self.server.DataDict['c'][List[i]]
					except:
						pass
					i = i + 1
				List = self.server.DataDict['db'].keys()
				i = 0
				while i != len(List):
					try:
						self.server.DataDict['db'][List[i]].close()
						del self.server.DataDict['db'][List[i]]
					except:
						pass
					i = i + 1
				#print
				#print 'Reopening environments...'
				for sEnvName in self.server.DataDict['env'].keys():
					#print 'EnvName=>', sEnvName
					sPath = self.server.DataDict['env_path'][sEnvName]
					CacheSizeTuple = self.server.DataDict['env_size'][sEnvName]
					self.server.DataDict['env'][sEnvName].close()
					self.server.DataDict['env'][sEnvName] = db.DBEnv()
					self.server.DataDict['env'][sEnvName].set_data_dir(sPath + '/data')
					self.server.DataDict['env'][sEnvName].set_tmp_dir(sPath + '/tmp')
					self.server.DataDict['env'][sEnvName].set_lg_dir(sPath + '/logs')
					self.server.DataDict['env'][sEnvName].set_cachesize(CacheSizeTuple[0], CacheSizeTuple[1])
					iFlags = db.DB_CREATE| db.DB_INIT_LOG| db.DB_INIT_MPOOL| db.DB_THREAD| db.DB_INIT_TXN| db.DB_RECOVER_FATAL
					self.server.DataDict['env'][sEnvName].open(sPath, iFlags)
				self.server.DataDict['lock'] = False
				ResponseDict['bResult'] = True
				#print self.server.DataDict
			elif sOp == 'openEnv':
				sPathEnv = RequestDict['sPath']
				self.server.DataDict['env_path'][sEnvName] = sPathEnv
				self.server.DataDict['env'][sEnvName] = db.DBEnv()
				self.server.DataDict['env'][sEnvName].set_data_dir(RequestDict['sDataDir'])
				self.server.DataDict['env'][sEnvName].set_tmp_dir(RequestDict['sTmpDir'])
				self.server.DataDict['env'][sEnvName].set_lg_dir(RequestDict['sLogDir'])
				CacheSizeTuple = RequestDict['CacheSizeTuple']
				if len(CacheSizeTuple) == 2:
					self.server.DataDict['env'][sEnvName].set_cachesize(CacheSizeTuple[0], CacheSizeTuple[1])					
				iFlags = RequestDict['iFlags']
				self.server.DataDict['env'][sEnvName].open(sPathEnv, iFlags)
				ResponseDict['bResult'] = True
				#print self.server.DataDict
			elif sOp == 'closeAllEnv':
				#print 'closeAllEnv'
				self.server.DataDict['lock'] = True
				List = self.server.DataDict['c'].keys()
				i = 0
				while i != len(List):
					try:
						#print 'cursor=>', List[i]
						self.server.DataDict['c'][List[i]].close()
						del self.server.DataDict['c'][List[i]]
					except:
						pass
					i = i + 1
				List = self.server.DataDict['db'].keys()
				i = 0
				while i != len(List):
					try:
						#print 'db=>', List[i]
						self.server.DataDict['db'][List[i]].close()
						del self.server.DataDict['db'][List[i]]
					except:
						pass
					i = i + 1
				for sEnv in self.server.DataDict['env'].keys():
					#print 'env=>', sEnv 
					self.server.DataDict['env'][sEnv].close()
					del self.server.DataDict['env'][sEnv]
					del self.server.DataDict['env_path'][sEnv]
				ResponseDict['bResult'] = True
				self.server.DataDict['lock'] = False
				#print self.server.DataDict
			elif sOp == 'lock_server':
				self.server.DataDict['lock'] = True
				#print self.server.DataDict
			elif sOp == 'unlock_server':
				self.server.DataDict['lock'] = False
				#print self.server.DataDict
			else:
				ResponseDict = self._doDb(RequestDict)
			doResponse = True
						
			if RequestDict.has_key('bResponse'):
				bResponse = RequestDict['bResponse']
				if bResponse:
					doResponse = True
				else:
					doResponse = False
			#print 'doResponse', doResponse
			#print ResponseDict
			if doResponse:
				sResponseDict = cPickle.dumps(ResponseDict)
				#SResponseDict = json.dumps(ResponseDict)
				#sResponseDict = jsonpickle.encode(ResponseDict)
				SocketRequest.sendall(sResponseDict)
		SocketRequest.close()
		fd.close()
		#print self.server.DataDict
	def finish(self):
		pass
